"""
Case Type   : ustore_DQL_SET_OPERATIONS
Case Name   : union前后select多列
Create At   : 2022-05-12
Owner       : nanyang12
Description :
    1.创建表
    2.使用copy命令插入数据
    3.union前后select多列
    4.环境清理
Expect      :
    1.创建成功
    2.数据插入成功
    3.成功
    4.清理成功
History     :
"""

import os
import subprocess
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class Ustore01(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----- {os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH('PrimaryDbUser')
        self.pri_root = Node('PrimaryRoot')
        self.com = Common()
        self.constant = Constant()
        self.table_name1 = 't_ustore_cte_0001_01'
        self.table_name2 = 't_ustore_cte_0001_02'
        self.table_name3 = 't_ustore_cte_0001_03'
        self.copy_file1 = 'store_returns_33.txt'
        self.copy_file2 = 'catalog_returns_33.txt'
        self.copy_file3 = 'customer_33.txt'
        self.cur_path_1 = os.path.join(macro.SCRIPTS_PATH, self.copy_file1)
        self.cur_path_2 = os.path.join(macro.SCRIPTS_PATH, self.copy_file2)
        self.cur_path_3 = os.path.join(macro.SCRIPTS_PATH, self.copy_file3)
        self.parent_path = os.path.dirname(macro.DB_INSTANCE_PATH)
        self.target_path1 = os.path.join(self.parent_path, self.copy_file1)
        self.target_path2 = os.path.join(self.parent_path, self.copy_file2)
        self.target_path3 = os.path.join(self.parent_path, self.copy_file3)

    def test_join(self):
        step_txt = '-----step1:创建表;expect: 创建成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""drop table if exists {self.table_name1}  CASCADE ;
                    drop table if exists {self.table_name2}  CASCADE ;
            create table {self.table_name1}
            (
                sr_returned_date_sk       integer                       ,
                sr_return_time_sk         integer                       ,
                sr_item_sk                integer               not null,
                sr_customer_sk            integer                       ,
                sr_cdemo_sk               integer                       ,
                sr_hdemo_sk               integer                       ,
                sr_addr_sk                integer                       ,
                sr_store_sk               integer                       ,
                sr_reason_sk              integer                       ,
                sr_ticket_number          bigint               not null,
                sr_return_quantity        integer                       ,
                sr_return_amt             decimal(7,2)                  ,
                sr_return_tax             decimal(7,2)                  ,
                sr_return_amt_inc_tax     decimal(7,2)                  ,
                sr_fee                    decimal(7,2)                  ,
                sr_return_ship_cost       decimal(7,2)                  ,
                sr_refunded_cash          decimal(7,2)                  ,
                sr_reversed_charge        decimal(7,2)                  ,
                sr_store_credit           decimal(7,2)                  ,
                sr_net_loss               decimal(7,2)                  
             )
            WITH (STORAGE_TYPE=USTORE) partition by range(sr_returned_date_sk)
            (
             partition p1 values less than (2451179) ,
             partition p2 values less than (2451544) ,
             partition p3 values less than (2451910) ,
             partition p4 values less than (2452275) ,
             partition p5 values less than (2452640) ,
             partition p6 values less than (2453005) ,
             partition p7 values less than (maxvalue)
            );
            create table {self.table_name2}
            (
                cr_returned_date_sk       integer                       ,
                cr_returned_time_sk       integer                       ,
                cr_item_sk                integer               not null,
                cr_refunded_customer_sk   integer                       ,
                cr_refunded_cdemo_sk      integer                       ,
                cr_refunded_hdemo_sk      integer                       ,
                cr_refunded_addr_sk       integer                       ,
                cr_returning_customer_sk  integer                       ,
                cr_returning_cdemo_sk     integer                       ,
                cr_returning_hdemo_sk     integer                       ,
                cr_returning_addr_sk      integer                       ,
                cr_call_center_sk         integer                       ,
                cr_catalog_page_sk        integer                       ,
                cr_ship_mode_sk           integer                       ,
                cr_warehouse_sk           integer                       ,
                cr_reason_sk              integer                       ,
                cr_order_number           bigint               not null,
                cr_return_quantity        integer                       ,
                cr_return_amount          decimal(7,2)                  ,
                cr_return_tax             decimal(7,2)                  ,
                cr_return_amt_inc_tax     decimal(7,2)                  ,
                cr_fee                    decimal(7,2)                  ,
                cr_return_ship_cost       decimal(7,2)                  ,
                cr_refunded_cash          decimal(7,2)                  ,
                cr_reversed_charge        decimal(7,2)                  ,
                cr_store_credit           decimal(7,2)                  ,
                cr_net_loss               decimal(7,2)
             ) WITH (STORAGE_TYPE=USTORE);
            create table {self.table_name3}
            (
                c_customer_sk             integer               not null,
                c_customer_id             char(16)              not null,
                c_current_cdemo_sk        integer                       ,
                c_current_hdemo_sk        integer                       ,
                c_current_addr_sk         integer                       ,
                c_first_shipto_date_sk    integer                       ,
                c_first_sales_date_sk     integer                       ,
                c_salutation              char(10)                      ,
                c_first_name              char(20)                      ,
                c_last_name               char(30)                      ,
                c_preferred_cust_flag     char(1)                       ,
                c_birth_day               integer                       ,
                c_birth_month             integer                       ,
                c_birth_year              integer                       ,
                c_birth_country           varchar(20)                   ,
                c_login                   char(13)                      ,
                c_email_address           char(50)                      ,
                c_last_review_date        char(10)
            )  WITH (STORAGE_TYPE=USTORE);"""
        self.log.info(cmd_sql)
        create_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(create_result)
        self.assertTrue(
            create_result.count(self.constant.TABLE_CREATE_SUCCESS) == 3,
            '执行失败:' + step_txt)

        step_txt = '-----step2:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(step_txt)
        text = '-----step2.1: 获取当前主机的IP地址;expect: 成功-----'
        self.log.info(text)
        cmd = "ifconfig -a|grep inet6 -a2|grep broadcast|awk '{print $2}'"
        self.log.info(cmd)
        self.cur_ip = subprocess.getoutput(cmd).strip()
        self.log.info(self.cur_ip)

        text = '-----step2.2: 复制文件到数据库主机对应目录 expect: 成功-----'
        self.log.info(text)
        if self.cur_ip == self.pri_sh.node.ssh_host:
            self.log.info('当前主机是数据库主机，无需远程复制')
            cmd = f"cp {self.cur_path_1} {self.parent_path};" \
                f"cp {self.cur_path_2} {self.parent_path};" \
                f"cp {self.cur_path_3} {self.parent_path};"
            self.log.info(cmd)
            res = self.pri_sh.node.sh(cmd).result()
            self.log.info(res)
        else:
            self.com.scp_file(self.pri_root, self.copy_file1,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file2,
                              self.parent_path)
            self.com.scp_file(self.pri_root, self.copy_file3,
                              self.parent_path)
            chmod_cmd = f"chmod 777 -R {self.parent_path};" \
                        f"ls -al {self.parent_path}"
            self.log.info(chmod_cmd)
            chmod_result = self.pri_root.sh(chmod_cmd).result()
            self.log.info(chmod_result)

        text = '-----step2.3: 查看数据库主机目标路径下文件 expect: 成功-----'
        self.log.info(text)
        cmd = f"ls -l {self.parent_path}| grep -E '{self.copy_file1}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file2}';" \
            f"ls -l {self.parent_path}| grep -E '{self.copy_file3}';"
        self.log.info(cmd)
        res = self.pri_root.sh(cmd).result()
        self.log.info(res)
        self.assertNotIn('No such file or directory', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file1}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file2}', res, '文件拷贝失败')
        self.assertIn(f'{self.copy_file3}', res, '文件拷贝失败')

        text = '-----step2.4:使用copy命令插入数据，expect: 数据插入成功-----'
        self.log.info(text)
        self.log.info('---------------使用copy命令插入数据------------------')
        copy_sql = f"copy {self.table_name1} from '{self.target_path1}' " \
            f"delimiters ',';" \
            f"copy {self.table_name2} from '{self.target_path2}' " \
            f"delimiters ',';" \
            f"copy {self.table_name3} from '{self.target_path3}' " \
            f"delimiters ',';"
        self.log.info(copy_sql)
        copy_result = self.pri_sh.execut_db_sql(copy_sql)
        self.log.info(copy_result)
        self.assertIn('COPY 2875', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 54', copy_result, '执行失败:' + step_txt)
        self.assertIn('COPY 10000', copy_result, '执行失败:' + step_txt)

        step_txt = '-----step3: union前后select多列 expect: 成功-----'
        self.log.info(step_txt)
        cmd_sql = f"""
        select  
        sr_return_amt          ,
        sr_return_tax          ,
        ''::numeric  ,
        sr_fee                 ,
        -1::smallint    ,
        sr_refunded_cash       ,
        sr_reversed_charge     ,
        sr_store_credit        ,
        sr_net_loss           
        from {self.table_name1}
        where substr(sr_returned_date_sk,-2)=79 ::smallint
        and sr_return_amt=0
        union  
        (with tmp as (select c_birth_day,c_birth_month from {self.table_name3}
        where c_birth_day=c_birth_month group by c_birth_day,c_birth_month)
        select 
        cr_return_amount     ,
        ''::numeric        ,
        cr_return_amt_inc_tax,
        -1               ,
        cr_return_ship_cost  ,
        0.00     ,
        cr_reversed_charge   ,
        cr_store_credit      ,
        cr_net_loss  
        from  {self.table_name2} 
        where cr_item_sk in (select c_birth_month from tmp where c_birth_day=1)
        )
        order by 1,2,3,4,5,6,7,8,9;"""
        self.log.info(cmd_sql)
        query_result = self.pri_sh.execut_db_sql(cmd_sql)
        self.log.info(query_result)
        self.assertIn('0 rows', query_result, '执行失败:' + step_txt)

    def tearDown(self):
        step_txt = '-----step4: 环境清理 expect:清理成功-----'
        self.log.info(step_txt)
        self.log.info('删除表')
        cmd_sql = self.pri_sh.execut_db_sql(f"""
                    drop table {self.table_name1} cascade;
                    drop table {self.table_name2} cascade;
                    drop table {self.table_name3} cascade;""")
        self.log.info(cmd_sql)
        text = '-----删除文件-----'
        self.log.info(text)
        rm_cmd = f"rm -rf {self.target_path1};" \
            f"rm -rf {self.target_path2};" \
            f"rm -rf {self.target_path3};"
        self.log.info(rm_cmd)
        self.com.get_sh_result(self.pri_root, rm_cmd)
        for s in [self.target_path1, self.target_path2]:
            cmd = f'if [ -f {s} ]; then echo "does exists"; ' \
                f'else echo "not exists"; fi'
            file_judgments = self.com.get_sh_result(self.pri_root, cmd)
            self.assertIn('not exists', file_judgments, "清理失败" + text)
        self.assertTrue(
            cmd_sql.count(self.constant.DROP_TABLE_SUCCESS) == 3,
            '执行失败:' + step_txt)
        self.log.info(f'----- {os.path.basename(__file__)} end-----')
